package com.young.ums.service.impl;

import com.young.common.exception.BaseException;
import com.young.common.util.CommonUtil;
import com.young.common.core.dal.service.IDataAccessService;
import com.young.common.util.Page;
import com.young.common.util.StringUtils;
import com.young.interfaces.log.annotation.Log;
import com.young.ums.core.ETopic;
import com.young.ums.core.PublishSubscribeCenter;
import com.young.ums.model.Button;
import com.young.ums.model.Navigate;
import com.young.ums.model.NavigateButton;
import com.young.common.model.enums.ETrashFlagEnum;
import com.young.ums.service.*;
import com.young.ums.util.UmsConstants;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

/**
* 按钮信息服务实现
* Created by imrookie on 2018-10-28.
*/
@Service("buttonService")
public class ButtonServiceImpl implements IButtonService {

    @Resource(name = "dataAccessService")
    IDataAccessService dataAccessService;//数据层服务

    @Resource(name="navigateButtonService")
    INavigateButtonService navigateButtonService;

    @Resource
    PublishSubscribeCenter publishSubscribeCenter;//发布订阅中心

    @Resource
    IRoleUserService roleUserService;//角色用户服务

    @Resource(name="roleNavigateService")
    IRoleNavigateService roleNavigateService;//角色资源服务

    @Resource(name="roleButtonService")
    IRoleButtonService roleButtonService;

    @Resource
    INavigateService navigateService;

    private static final Logger logger = LoggerFactory.getLogger(ButtonServiceImpl.class);

    private static final String MAPPER = "com.young.ums.mapper.button";//mapper的namespace

    //获取数据列表
    @Log("查询按钮列表")
    @Override
    public List<Button> getList(Button obj) {
        return dataAccessService.getList(MAPPER + ".getList", obj);
    }

    //获取数据列表(分页)
    @Log("分页查询按钮")
    @Override
    public List<Button> getPage(Button obj, Page page) {
        return dataAccessService.getList(MAPPER + ".getList", obj, page);
    }

    //查询单条
    @Log("按钮查询")
    @Override
    public Button get(String id) {
        return dataAccessService.getObject(MAPPER + ".get", id);
    }

    //统计数量
    @Log("统计按钮数量")
    @Override
    public int count(Button obj) {
        return dataAccessService.getObject(MAPPER + ".count", obj);
    }

    //修改
    @Log("修改按钮")
    @Override
    public int update(Button obj) {
        obj.setUpdateTime(new Date());
        return dataAccessService.update(MAPPER + ".update", obj);
    }

    //批量删除
    @Log("批量删除按钮")
    @Override
    public int delete(String[] idArr) {
        int i = 0;
        for(String id : idArr){
            i += this.delete(id);
        }
        return i;
    }

    //删除单条
    @Log("删除按钮")
    @Override
    public int delete(String id) {
        int i = dataAccessService.delete(MAPPER + ".delete", id);
        //向发布订阅中心发布删除消息
        publishSubscribeCenter.publish(ETopic.BUTTON_DEL, id);
        return i;
    }

    //插入
    @Log("插入按钮")
    @Override
    public int insert(Button obj) {
        if (StringUtils.isBlank(obj.getId())){//设置默认id
            obj.setId(CommonUtil.getUUID());
        }
        if (StringUtils.isBlank(obj.getCategory())){//默认按钮分组
            obj.setCategory(UmsConstants.DEFAULT.BUTTON_CATEGORY);
        }
        obj.setCreateTime(new Date());
        obj.setUpdateTime(new Date());
        obj.setTrashFlag(ETrashFlagEnum.VALID.type);//默认按钮是正常的
        return dataAccessService.insert(MAPPER + ".insert", obj);
    }

    /**
     * 创建按钮并且关联指定导航
     *
     * @param button     按钮信息
     * @param navigateId 导航id
     * @return
     */
    @Log("创建按钮并且关联指定导航")
    @Override
    public int insertAndRelevanceNavigate(Button button, String navigateId) {
        if (StringUtils.isBlank(navigateId)){
            throw new BaseException("导航编号不允许为空");
        }
        //1.插入按钮信息
        this.insert(button);
        //2.建立关联关系
        NavigateButton navigateButton = new NavigateButton();
        navigateButton.setNavigateId(navigateId);
        navigateButton.setButtonId(button.getId());
        return navigateButtonService.insert(navigateButton);
    }

    /**
     * 批量克隆按钮并关联到资源
     *
     * @param buttonIds  待克隆的按钮编号集合
     * @param navigateId 资源编号
     * @param userId     当前登录用户编号
     * @param category   按钮分组
     * @return
     */
    @Log("批量克隆按钮并关联到资源")
    @Override
    public int cloneButtonAndRelevanceNavigate(String[] buttonIds, String navigateId, String userId, String category) {
        //验证资源是否有效
        Navigate navigate = navigateService.get(navigateId);
        if (navigate == null){
            throw new BaseException("克隆按钮并关联操作失败:资源不存在");
        }
        //根据按钮编号查询按钮
        List<Button> list = this.getButtonListByIds(Arrays.asList(buttonIds));
        if (list == null || list.size() == 0){
            throw new BaseException("克隆按钮并关联操作失败:按钮不存在");
        }
        int i = 0;
        //装配按钮信息
        for (Button button : list){
            //重置按钮编号,创建人,创建时间,分组等信息
            button.setId(CommonUtil.getUUID());
            button.setCreateUserId(userId);
            button.setCreateUserId(userId);
            button.setCreateTime(new Date());
            button.setUpdateTime(new Date());
            button.setCategory(CommonUtil.getDefaultValue(category, UmsConstants.DEFAULT.BUTTON_CATEGORY_CLONE));//默认克隆按钮组
            //执行插入并关联资源
            i += this.insertAndRelevanceNavigate(button, navigateId);
        }
        return i;
    }

    //批量插入
    @Log("批量插入按钮")
    @Override
    public int batchInsert(List<Button> list) {
        int i = 0;
        for(Button item : list){
            i += this.insert(item);
        }
        return i;
    }

    /**
     * 查询按钮分组
     * @return
     */
    @Log("查询按钮分组")
    @Override
    public List<String> getButtonCategoryList() {
        return dataAccessService.getList(MAPPER + ".getButtonCategoryList", null);
    }

    /**
     * 根据资源ID查询按钮列表
     *
     * @param navigateId 资源导航id
     * @return
     */
    @Log("根据资源ID查询按钮列表")
    @Override
    public List<Button> getButtonListByNavigateId(String navigateId) {
        //根据资源id查询关联的按钮id集合
        List<String> btnIds = navigateButtonService.getButtonIdsByNavigateId(navigateId);
        if (btnIds != null && btnIds.size() > 0){
            return this.getButtonListByIds(btnIds);
        }
        return null;
    }

    /**
     * 根据按钮id集合批量查询按钮信息
     *
     * @param btnIds
     * @return
     */
    @Log("根据按钮id集合批量查询按钮信息")
    @Override
    public List<Button> getButtonListByIds(List<String> btnIds) {
        if (btnIds == null || btnIds.size() == 0){
            throw new BaseException("根据编号集合查询按钮失败:编号集合为空");
        }
        return dataAccessService.getList(MAPPER + ".getButtonListByIds", btnIds);
    }

    /**
     * 获取资源下权限范围内的按钮
     *
     * @param navigateId 资源id
     * @param userId     用户id
     * @return
     */
    @Log("获取资源下权限范围内的按钮")
    @Override
    public List<Button> getButtonListInNavigate(String navigateId, String userId) {
        if (StringUtils.isBlank(navigateId) || StringUtils.isBlank(userId)){
            throw new BaseException("资源编号无效或用户编号无效");
        }
        //根据用户编号查询用户拥有的角色
        String[] roleIds = roleUserService.getRoleIdsByUserId(userId);
        if (roleIds == null || roleIds.length == 0){//若该用户不存在角色信息,返回空
            logger.info("[获取资源下权限范围内的按钮] 当前用户[{}]不存在关联角色,返回null", userId);
            return null;
        }
        logger.info("[获取资源下权限范围内的按钮] 当前用户[{}]的角色={}", userId, roleIds);
        //判断用户是否具备该资源的权限
        if (!roleNavigateService.hasRelevanced(roleIds, navigateId)) {
            logger.info("[获取资源下权限范围内的按钮] 当前用户[{}]不具备资源[{}]的权限(用户的角色信息={}),返回null", userId, navigateId, roleIds);
            return null;
        }
        logger.info("[获取资源下权限范围内的按钮] 当前用户[{}]具备资源[{}]的权限", userId, navigateId);
        //根据资源编号查询资源下的按钮id集合
        List<String> btnIds = navigateButtonService.getButtonIdsByNavigateId(navigateId);
        if (btnIds == null || btnIds.size() == 0) {//若资源下没有按钮,则返回空
            logger.info("[获取资源下权限范围内的按钮] 当前资源[{}]不存在关联按钮,返回null", navigateId);
            return null;
        }
        logger.info("[获取资源下权限范围内的按钮] 资源[{}]下的按钮有: {}", navigateId, btnIds);
        //查询用户拥有的角色关联的按钮
        List<String> btnList = roleButtonService.getButtonIdsByRoleIds(roleIds);
        if (btnList == null || btnList.size() == 0) {
            logger.info("[获取资源下权限范围内的按钮] 当前用户[{}]拥有的角色[{}]没有关联任何按钮,返回null", userId, roleIds);
            return null;
        }
        logger.info("[获取资源下权限范围内的按钮] 用户[{}]拥有的按钮权限有: {}", userId, btnList);
        //对资源下的按钮(btnIds)进行权限过滤(btnList)
        Iterator<String> iterator = btnIds.iterator();
        while (iterator.hasNext()){
            String btn = iterator.next();
            if (!btnList.contains(btn)){//权限范围内不存在此按钮则剔除
                iterator.remove();
            }
        }
        //若经过权限过滤后为空,说明当前用户不具备该资源下的按钮权限,则返回null
        if (btnIds == null || btnIds.size() == 0) {
            logger.info("[获取资源下权限范围内的按钮] 用户[{}]在资源[{}]不具备任何按钮权限,返回null", userId, navigateId);
            return null;
        }
        logger.info("[获取资源下权限范围内的按钮] 当前用户[{}]拥有角色[{}],在资源[{}]下拥有的按钮权限为:{}", userId, roleIds, navigateId, btnIds);
        //根据最终的按钮编号查询按钮信息返回
        return this.getButtonListByIds(btnIds);
    }

}